perm filename EXPRS.SAI[AL,HE] blob sn#501007 filedate 1980-03-10 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00009 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	IFCR ¬DECLARATION(EXTENDED_COMPILATION) THENC
C00004 00003	! new_var,new_lbl,asglbl
C00006 00004	! dtype, vtcheck
C00008 00005	! vnode managers: add_vnode, okvnget
C00011 00006	! inval0, invalidate, eval, getvalue, arrayref, vchange, dchange, killvar
C00021 00007	! expeqv
C00023 00008	! invsimp
C00025 00009	! evalexpr 
C00034 ENDMK
C⊗;
IFCR ¬DECLARATION(EXTENDED_COMPILATION) THENC
    ENTRY;  COMMENT  Requirements, initialization of constants;

    BEGIN "EXPRS"
    DEFINE EXPRS_TERNAL = "INTERNAL";

    IFCR ¬ DECLARATION(CREFFING) THENC DEFINE CREFFING = "FALSE";ENDC
    IFCR ¬ CREFFING THENC
	REQUIRE "ALREQ.HDR[AL,HE]" SOURCE_FILE;
	REQUIRE "GOBBLE.HDR[AL,HE]" SOURCE_FILE;
    ENDC
    REDEFINE $$PRGID "[]" = ["EXPRS"];
IFCR CREFFING THENC REQUIRE $$PRGID MESSAGE;ENDC
ENDC

INTERNAL INTEGER CURTIME; INITIALIZE (CURTIME←1);
! new_var,new_lbl,asglbl;

INTERNAL RPTR(VARIABLE) PROCEDURE NEW_VAR(STRING NAME; INTEGER DT; RBLK BID);
    BEGIN
    RVAR VAR;
    VAR ← NEW_RECORD(VARIABLE);
    VARIABLE:NAME[VAR] ← NAME;
    VARIABLE:DATATYPE[VAR] ← DT;
    VARIABLE:BLK[VAR] ← BID;
    IF BID ≠ RNULL THEN
	IF DT = EVENT_DTYPE THEN CONSON(VAR,BLOCK:EVTS[BID])
			    ELSE CONSON(VAR,BLOCK:VARS[BID]);
    RETURN(VAR);
    END;

INTERNAL RPTR(LBLVAR) PROCEDURE NEW_LBL(STRING NAME; INTEGER DT; RBLK BID);
    BEGIN
    RPTR(LBLVAR) L;
    L ← NEW_RECORD(LBLVAR);
    LBLVAR:DATATYPE[L] ← DT;
    LBLVAR:BLK[L] ← BID;
    LBLVAR:NAME[L] ← NAME;
    RETURN(L);
    END;

INTERNAL RANY PROCEDURE ASGLBL(RPTR(LBLVAR) L;RPTR(ANY_CLASS) SEM);
    BEGIN
    IF RECTYPE(SEM) = LOC(STMNT) THEN ! have the stmnt point to the label;
	BEGIN
	STMNT:STLAB[SEM] ← L;
	IF RECTYPE(STMNT:SEMANTICS[SEM]) = LOC(CMON) THEN
	    SEM ← STMNT:SEMANTICS[SEM];
	END;
    IF RECTYPE(SEM) = LOC(CMON) THEN LBLVAR:DATATYPE[L] ← OMNLAB_DTYPE;
    LBLVAR:SEMANTICS[L] ← SEM;
    RETURN(SEM)
    END;
! dtype, vtcheck;

INTERNAL INTEGER SIMPLE PROCEDURE DTYPE(INTEGER DT);
    START_CODE
    MOVE    0,DT; ! this is cretinous, but ...;
    MOVEI   1,0;
    CAIN    0,SVAL_DTYPE;
    MOVEI   1,SVAL;
    CAIN    0,V3ECT_DTYPE;
    MOVEI   1,V3ECT;
    CAIN    0,ROTN_DTYPE;
    MOVEI   1,ROTN;
    CAIN    0,TRANS_DTYPE;
    MOVEI   1,TRANS;
    CAIN    0,FRAME_DTYPE;
    MOVEI   1,FRAME;
    END;

INTERNAL RPTR(VALU$) PROCEDURE VTCHECK(RVAR VAR; RPTR(VALU$) VAL);
    BEGIN
    INTEGER DT,VART;
    DT ← VARIABLE:DATATYPE[VAR];
    VART ← RECTYPE(VAL);
    IF VART ≠ DTYPE(DT) THEN
	IF DT=FRAME_DTYPE ∧ VART=LOC(TRANS) THEN RETURN(NEW_FRAME(VAL))
	  ELSE USERERR(1,1,"TYPE MISMATCH IN VTCHECK");
    RETURN(VAL)
    END;

RPTR(VALU$) PROCEDURE TFCVT(RPTR(VALU$) V);	! Used by evalexpr & eval;
    IF RECTYPE(V)=LOC(FRAME) THEN RETURN(FRAME:VAL[V])
	ELSE RETURN(V);
! vnode managers: add_vnode, okvnget;

PROCEDURE ADD_VNODE(RPTR(VNODE) VN, VL);
    BEGIN	! Add vnode VN to vnode list headed by VL;
    RPTR(VNODE) VO;
    WHILE VL≠RNULL ∧ VNODE:VAR[VL] < VNODE:VAR[VN] DO VL ← VNODE:NEXT[(VO←VL)];
    VNODE:NEXT[VN] ← VL;
    VNODE:NEXT[VO] ← VN		! Splice into list;
    END;

RPTR(VNODE) PROCEDURE OKVNGET(RVAR VAR; RTHREAD WLD);
    BEGIN

    ! returns a graph node for VAR which may be modified in
    world WLD without causing strange side effects in other
    worlds;

    RPTR(VNODE) GN;
    GN ← VARIABLE:PLNVAL[VAR];
    IF GN = RNULL ∨ VNODE:THREAD[GN] ≠ WLD THEN
	BEGIN	! Make up a new vnode for this thread;
	GN ← NEW_RECORD(VNODE);
	VNODE:VAR[GN] ← VAR;				! Add back pointers;
	VNODE:THREAD[GN] ← WLD;
	VNODE:OLDVAL[GN] ← VARIABLE:PLNVAL[VAR];	! If any;
	VNODE:INVMARK[GN] ← -1;
	VARIABLE:PLNVAL[VAR] ← GN;
	ADD_VNODE(GN,THREAD:VALS[WLD]);			! Link onto value thread;
	END;
    RETURN(GN);
    END;
! inval0, invalidate, eval, getvalue, arrayref, vchange, dchange, killvar;

! These routines perform graph node operations in a named planning world.
  Their individual actions are those specified in the AL report. ;

RECURSIVE PROCEDURE INVAL0(RVAR VAR; RTHREAD WLD; REFERENCE RCELL INVLSEEN);
    BEGIN
    ! procedure used as working loop of invalidate:
      (1) looks to see if it has already invalidated VAR by
	    checking whether id of VAR is in INVLSEEN.
      (2) if plnval vnode is null or valid, then
	    gets a vnode for this world & sets INVMARK to -1.
      (3) processes all dependent nodes.
    ;
    INTEGER RT;
    RPTR(VNODE) GN;
    RPTR(CALC) C;

    IF MEMQ(VAR,INVLSEEN) THEN RETURN;
    CONSON(VAR,INVLSEEN);

    GN ← OKVNGET(VAR,WLD);	! Get a vnode for this world;
    VNODE:INVMARK[GN] ← -1;	! It's no longer valid;
    C ← VARIABLE:CALCS[VAR];
    WHILE C ≠ RNULL DO		! Invalidate everyone we're affixed to;
	BEGIN
	IF CALC:TYPE[C] ≠ 0 THEN	! Non-rigid + frame 1;
	    INVAL0(CALC:OTHER[C],WLD,INVLSEEN);
! ***** ????What happens to the bvar for non-rigid affixments here???? *****;
	C ← CALC:NXTCALC[C]
	END
    END;

INTERNAL RPTR(VNODE) RECURSIVE PROCEDURE INVALIDATE(RVAR VAR; RTHREAD WLD);
    BEGIN
    RCELL INVLSEEN;
    INVLSEEN ← RNULL;
    INVAL0(VAR,WLD,INVLSEEN);
    RETURN(VARIABLE:PLNVAL[VAR])
    END;

RECURSIVE RPTR(VNODE) PROCEDURE EVAL (RVAR VAR; INTEGER T; RTHREAD WLD);
    BEGIN
    INTEGER I;
    RPTR(VNODE) GN,OVN,BVN;
    RPTR(CALC) C;

    GN ← VARIABLE:PLNVAL[VAR];
    ! see if we already have a valid value, or have already looked for one;
    IF GN ≠ RNULL ∧ (VNODE:INVMARK[GN]=0 ∨ VNODE:INVMARK[GN]=T) THEN RETURN(GN);
    ! nope - have to use a calc;
    GN ← OKVNGET(VAR,WLD);
    VNODE:INVMARK[GN] ← T;
    FOR I ← 1 STEP 1 UNTIL 2 DO
	BEGIN
	C ← VARIABLE:CALCS[VAR];
	WHILE C ≠ RNULL DO
	    BEGIN
	    IF CALC:TYPE[C] ≠ 2 THEN        ! Non-rigid + frame 2;
		BEGIN
		IF I = 1 THEN
		    BEGIN  ! First time see if someone's already valid;
		    OVN ← VARIABLE:PLNVAL[CALC:OTHER[C]];
		    BVN ← VARIABLE:PLNVAL[CALC:BVAR[C]];
		    END
		ELSE
		    BEGIN  ! Second time try to validate someone;
		    OVN ← EVAL(CALC:OTHER[C], T, WLD);
		    BVN ← EVAL(CALC:BVAR[C], T, WLD)
		    END;
		IF OVN ≠ RNULL ∧ VNODE:INVMARK[OVN] = 0
		 ∧ BVN ≠ RNULL ∧ VNODE:INVMARK[BVN] = 0 THEN  ! Both are valid;
		    BEGIN
		    RPTR(TRANS,FRAME) T1,T2;
		    T1 ← TFCVT(VNODE:VAL[OVN]);
		    T2 ← TFCVT(VNODE:VAL[BVN]);
		    IF CALC:TYPE[C] LAND 2 THEN T2 ← TINVRT(T2);  ! Frame 2;
		    VNODE:VAL[GN] ← NEW_FRAME(TTMUL(T1,T2));
		    VNODE:INVMARK[GN] ← 0;
		    RETURN(GN)
		    END
		END;
	    C ← CALC:NXTCALC[C]
	    END
	END;
    RETURN(GN); ! we did the best we could;
    END;

INTERNAL RPTR(VALU$) PROCEDURE GETVALUE (RVAR VAR;
						RTHREAD WLD; BOOLEAN OK(FALSE));
    BEGIN
    RPTR(VNODE) GN;
    GN ← VARIABLE:PLNVAL[VAR];
    IF GN = RNULL  ∨  VNODE:INVMARK[GN] ≠ 0 THEN
	GN ← EVAL(VAR,CURTIME←CURTIME+1,WLD);
    IF GN = RNULL ∨ VNODE:INVMARK[GN] ≠ 0 THEN
	BEGIN
	IF ¬OK THEN PRINT(CRLF & "WARNING: ", VARIABLE:NAME[VAR],
			  " has no plan value - will use zero" & CRLF);
	CASE VARIABLE:DATATYPE[VAR] OF
	  BEGIN                         ! really return something so we;
	[SVAL_DTYPE]    RETURN(FALSEV); !   don't generate more error;
	[V3ECT_DTYPE]   RETURN(NILVECT); !  messages than need be;
	[ROTN_DTYPE]    RETURN(NILROTN);
	[TRANS_DTYPE]   RETURN(NILTRANS);
	[FRAME_DTYPE]   RETURN(NILDEPROACH);
	 ELSE           RETURN(RNULL)
	  END
	END;
    RETURN(VNODE:VAL[GN]);
    END;

INTERNAL RECURSIVE RVAR PROCEDURE ARRAYREF(REXPR E; RTHREAD WLD);
    BEGIN
    INTEGER I,J,N;
    RCELL SS;
    RPTR(ARRAYDEF) H;
    SS ← EXPRN:ARGS[E];
    H ← LLOP(SS);
    I ← N ← 1;
    WHILE SS ≠ RNULL ∧ I ≤ ARRAYDEF:NUMDIMS[H] DO
	BEGIN
	J ← SVAL:VAL[EVALEXPR(LLOP(SS),WLD)]; ! get subscript's value;
	IF J > ARRAYDEF:BDVALS[H][I,1] THEN
	    BEGIN
	    USERERR(1,1,"ARRAYREF: SUBSCRIPT TOO LARGE");
	    J ← ARRAYDEF:BDVALS[H][I,1]
	    END;
	IF (J ← J - ARRAYDEF:BDVALS[H][I,0]) < 0 THEN
	    BEGIN
	    USERERR(1,1,"ARRAYREF: SUBSCRIPT TOO SMALL");
	    J ← 0
	    END;
	N ← N + J * ARRAYDEF:BDVALS[H][I,2];
	I ← I + 1
	END;
    RETURN(ARRAYDEF:VARS[H][N])
    END;

INTERNAL RECURSIVE PROCEDURE VCHANGE(RPTR(VARIABLE,EXPRN) VAR;
				    RPTR(VALU$) NEWV; RTHREAD WLD);
    BEGIN
    RPTR(VNODE) GN;
    RPTR(CALC) C;
    IF (RECTYPE(VAR)=LOC(EXPRN)) ∧ (EXPRN:OP[VAR]=AREF_OP) THEN
	VAR ← ARRAYREF(VAR,WLD);
    GN ← INVALIDATE(VAR,WLD);
    IF NEWV ≠ RNULL THEN
	BEGIN
	VNODE:VAL[GN] ← VTCHECK(VAR,NEWV);
	VNODE:INVMARK[GN] ← 0;
	C ← VARIABLE:CALCS[VAR];
	WHILE C ≠ RNULL DO
	    BEGIN
	    IF CALC:TYPE[C] = 0 THEN        ! Non-rigid + frame 1;
		VCHANGE(CALC:BVAR[C],TTMUL(
		    TINVRT(GETVALUE(CALC:OTHER[C],WLD,TRUE)), NEWV), WLD);
	    C ← CALC:NXTCALC[C]
	    END
	END
      ELSE VNODE:INVMARK[GN] ← -1;
    END;

INTERNAL PROCEDURE DCHANGE(RPTR(VARIABLE,EXPRN) VAR; 
					RPTR(VALU$) NEWV; RTHREAD WLD);
    BEGIN
    RPTR(VNODE) GN;
    IF (RECTYPE(VAR)=LOC(EXPRN)) ∧ (EXPRN:OP[VAR]=AREF_OP) THEN
	VAR ← ARRAYREF(VAR,WLD);
    GN ← VARIABLE:DEPR[VAR];
    IF GN = RNULL ∨ VNODE:THREAD[GN] ≠ WLD THEN
	BEGIN	! Make up a new vnode for this thread;
	GN ← NEW_RECORD(VNODE);
	VNODE:VAR[GN] ← VAR;				! Add back pointers;
	VNODE:THREAD[GN] ← WLD;
	VNODE:OLDVAL[GN] ← VARIABLE:DEPR[VAR];		! If any;
	VARIABLE:DEPR[VAR] ← GN;
	ADD_VNODE(GN,THREAD:DEPRS[WLD]);	! Link onto value thread;
	END;
    VNODE:VAL[GN] ← NEWV
    END;

INTERNAL PROCEDURE KILLVAR(RTHREAD WLD; RVAR VAR);
    BEGIN
    RPTR(CALC) C;
    C ← VARIABLE:CALCS[VAR];
    WHILE C ≠ RNULL DO			! Unfix us from rest of world;
	BEGIN
	DO_UNFIX(WLD,VAR,CALC:OTHER[C]); ! Unfix will validate them if possible;
	C ← VARIABLE:CALCS[VAR]
	END
    END;
! expeqv;

! Symbolic comparison of expressions.  not very bright about
  commutative laws, etc. Returns TRUE if it thinks that E1 ≡ E2;

INTERNAL RECURSIVE BOOLEAN PROCEDURE EXPEQV(RPTR(EXPRN,VALU$,VARIABLE) E1,E2);
    BEGIN
    INTEGER T1,T2;
    IF E1 = E2 THEN RETURN(TRUE);
    T1←RECTYPE(E1);T2←RECTYPE(E2);
    IF T1≠ T2 THEN RETURN(FALSE);
    IF T1= LOC(VARIABLE) THEN RETURN(FALSE); ! had to be eq;
    IF T1= LOC(SVAL) THEN RETURN(SVAL:VAL[E1]=SVAL:VAL[E2]);
    IF T1= LOC(V3ECT) THEN RETURN(V3CMP(E1,E2)=0);
    IF T1= LOC(ROTN) THEN RETURN(ROTCMP(E1,E2)=0);
    IF T1= LOC(TRANS) THEN RETURN(TRANSCMP(E1,E2)=0);
    IF T1= LOC(FRAME) THEN RETURN(TRANSCMP(FRAME:VAL[E1],FRAME:VAL[E2])=0);
    IF T1= LOC(EXPRN) THEN
	BEGIN
	RCELL C1,C2;
	IF EXPRN:OP[E1]≠EXPRN:OP[E2] THEN RETURN(FALSE);
	IF EXPRN:DATATYPE[E1]≠EXPRN:DATATYPE[E2] THEN RETURN(FALSE);
	C1←EXPRN:ARGS[E1];C2←EXPRN:ARGS[E2];
	WHILE C1≠NULL_RECORD ∧ C2≠NULL_RECORD DO
	    BEGIN
	    IF ¬EXPEQV(CELL:CAR[C1],CELL:CAR[C2]) THEN RETURN(FALSE);
	    C1←CELL:CDR[C1];
	    C2←CELL:CDR[C2];
	    END;
	RETURN(C1=C2);
	END;

    USERERR(1,1,"EXPEQV: CONFUSION");
    RETURN(FALSE);
    END;
! invsimp;

INTERNAL REXPR RECPROC INVSIMP(REXPR E);
    BEGIN
    REXPR EE;RCELL C,CC;
    BOOLEAN FLAG;

    IF RECTYPE(E)≠LOC(EXPRN) THEN RETURN(E);

    FLAG←FALSE;
    C←EXPRN:ARGS[E];

    IF EXPRN:OP[E]=TINVRT_OP THEN
	BEGIN
	EE←INVSIMP(CELL:CAR[C]);
	IF RECTYPE(AE)=LOC(EXPRN) THEN
	    BEGIN
	    IF EXPRN:OP[EE]=TINVRT_OP THEN RETURN(CELL:CAR[EXPRN:ARGS[EE]])
	    END;
	IF EE≠CELL:CAR[C] THEN
	    BEGIN
	    FLAG←TRUE;
	    CC←CONS(EE,NULL_RECORD)
	    END;
	END
    ELSE WHILE C≠NULL_RECORD DO
	BEGIN
	EE←INVSIMP(LLOP(C));
	CC←APPEND(CC,COH
&Q∃
Y≥+1_1%
∨%λR$v~∀∪→→β∂?Q%+
v4∀∪≥⊂v~∀@@A∪↓
→β∞↓)⊃≤↓%)+I≤Q≥\11!I≤Q1A%≤u	¬)β)3A7:11!%8u∨!7∃:Yπε$R~∀∩@@A1'
A%∃)+%≤!
R~∀@@A9λv~∀_BAKYCYKqAd@v~(~∃∪≥Q%≥β0A%!)HQ-β→THRA%∃π!%∨A-β11!$!%!)$!1!%8Y-β%%β¬→
1-β→*⊂RA
wI)⊃%¬λA/→⊂Rv~∀@@A¬∃∂∪≤~(~∀@@@BAKYCYkCQKfAi!JAaY¬]]S]≤AmCYUJA←L↓Kqae∃ggS←8[YSW∀AiQS9NA
A%\~∀@@@@A]←eYH↓/→λ@_AeKiUe]fA∧AmCYUJ@QJ9N\XAYKGi←HXAgm¬XXAiIC]fRv~∀~(@@@AI!)$Q
→_R↓εv~∀@@A%A)$Q-¬→*HR↓,bY,HY,fv4∀@@@↓∪≥)≥$AQ3 v~(~∀@@A∪A∀{≥+→01%π=%λA)!≤A%∃)+%≤!
Rv~(~∀@@A)3@A>A%∃π)3!∀Q
Rv4∀@@@↓∪AQ3 @z↓→∨εQYβ%∪β	→
RAQ⊃≤AI)+%8Q∂)Yβ→+
!
Y/→⊂RR~∀@@A1'
A∪_A)3@{→∨ε!'-β_$@>AQ3 {→=εQ
%­
R@|A)3@{→∨ε!)%β≥LR@>~(∪)3@{→∨ε!,gπPR@>A∃)3 {1∨εQ%=)≤RAQ⊃≤~(∩@@@↓%)+I≤Q
R4∀@@@↓→'
↓∪AQ3 {→=εQ
∨Iπ
RAQ⊃≤~(∪%)U%≤Q≥∃.1'-¬_P`R$∩BA≥<ASIK∧AoQCPAiQJ↓CGik¬XAmC1kJAo%YXAE∀v~∀@@A→M
A∪↓)3 m→∨εQ∃1!%≤$A)⊃8~∀∪¬∃∂∪≤~(∪+'I%$PDXbXE∃-β→a!$tA	βλAβI∂+≠9(DRv4∀∪%Q+%≤Q9+→_1Iπ∨%⊂Rv~∀%≥λv4∀@@@↓π?1A%≤uβI∂'7tv~∀@@A∪↓1!%8u∨!7∃:{β%∃1∨ >A1A%≤u∨A7:{
β→_1= @>A∃1!%≤i∨!7t{#+I21∨ ~∀∪)!≤Aπ⎇%≥+→0v~∀@@A∪↓ε7≥+1_1%
∨%λAQ⊃≤AXc?)

-(QYβ→1A$Q→→= QεR1/→λR$v~∀@@A∪↓ε7≥+1_1%
∨%λAQ⊃≤AXe?)

-(QYβ→1A$Q→→= QεR1/→λR$v~∀@@A∪↓ε7≥+1_1%
∨%λAQ⊃≤AXg?)

-(QYβ→1A$Q→→= QεR1/→λR$v~∀~(@@@A
β'
A∃1!%≤i∨!7tA∨~(∩@@@↓¬∂∪8~∀~∃m≥≡1∨A:@@@@@@@↓%)+I≤Q,b$v~∀~)7'πβ1%λ1∨A:~∃7E+%2a∨!:@@@@AI)+%8Q
β→M,Rv4∀~∃7Mβ¬&1=!:@@@@@AI)+%8Q≥.a'-β_!β¬&AM-β_uYβ→7,E:RRv4∀~∃7M≥∞1=!:@@@@@AI)+%8Q≥.a'-β_ ['-β0u-β→m,c:R$v~∀~)7'β	⊂1∨!:@@@@A%)U%≤Q≥∃.1'-¬_Q'-¬_u-β17,c:-'-β_i-β→7Xe:RRl~∀~∃m''+∧a∨!:@@@@@↓%)+I≤Q≥\1'-β0Q'-β0u-β→m,c:[M-β_uYβ→7,I:RRv4∀~∃7M≠+_1=!:@@@@@AI)+%8Q≥.a'-β_!'-β_i-β→7Xc:U'Yβ_u-¬→7,etRRv~(~∃7'⊃∪,1∨A:@@@@@A%∃)+%≤!≥.1M-β_QM-β_uYβ→7,E:←'-¬_u-β17,e:$Rv~∀4∃7'a 1∨!t@@@@@A%Q+%≤Q9.1'Yβ_Q'Yβ_u-¬→7,cu='-β0u-β→m,e:R$v~∀~)7≠β0a∨!:@@@@@A%)U%≤Q≥∃.1'-¬_Q'-¬_u-β17,c:↓≠β0AM-β_uYβ→7,I:RRv4∀~∃75∪≤1∨A:@@@@@@AI)+%8Q≥.a'-β_!'-β_i-β→7Xc:A≠%≤A'-¬_u-β17,e:$Rv~∀4∃7∪≥P1∨!:@@@@@A%Q+%≤Q9.1'Yβ_Q'Yβ_u-¬→7,ctA	∪,bRRv4∀~∃7⊃∪,1∨A:@@@@@@AI)+%8Q≥.a'-β_!'-β_i-β→7Xc:A	%,A'-¬_u-β17,e:$Rv~∀4∃7≠∨⊂1∨!:@@@@@A%Q+%≤Q9.1'Yβ_Q'Yβ_u-¬→7,ctA≠∨λ↓'-β_i-β→7Xe:RRl~∀~∃m'→(1=!:@@@@@@↓%)+I≤Q≥\1'-β0Q'-β0u-β→m,c:yM-β_uYβ→7,I:RRv4∀~∃7M"1∨A:@@@@@@AI)+%8Q≥.a'-β_!'-β_i-β→7Xc:{'Yβ_u-¬→7,etRRv~(~∃7'1
1∨!t@@@@@@A%∃)+%≤!≥.1M-β_QM-β_uYβ→7,E:9'-¬_u-β17,e:$Rv~∀4∃7'∂∀1∨!:@@@@@A%Q+%≤Q9.1'Yβ_Q'Yβ_u-¬→7,ct;'-β0u-β→m,e:R$v~∀~)7'≥
a∨!:@@@@@A%)U%≤Q≥∃.1'-¬_Q'-¬_u-β17,c:m'-β_i-β→7Xe:RRl~∀~∃m'∂(1=!:@@@@@@↓%)+I≤Q≥\1'-β0Q'-β0u-β→m,c:⎇M-β_uYβ→7,I:RRv4∀~∃7¬≥λ1∨A:@@@@@@AI)+%8Q≥.a'-β_!'-β_i-β→7Xc:	'Yβ_u-¬→7,etRRv~(~∃7∨H1∨!:@@@@@@A%∃)+%≤!≥.1M-β_QM-β_uYβ→7,E:?'-¬_u-β17,e:$Rv~∀4∃7≥∨P1∨!:@@@@@A%Q+%≤Q9.1'Yβ_PM-β_uYβ→7,E:RRv4∀~∃7a∨$1∨A:@@@@@@AI)+%8Q≥.a'-β_!'-β_i-β→7Xc:-'Yβ_u-¬→7,etRRv~(~∃7E,1∨!t@@@@@@A%∃)+%≤!≥.1M-β_QM-β_uYβ→7,E:='-¬_u-β17,e:$Rv~∀4∃7-≠¬∂≤1∨A:@@@@A%Q+%≤Q9.1'Yβ_Q'E%(Q,M	∨(QXbY,b$RRRv4∀~∃7Y	∨(1=!:@@@@@AI)+%8Q≥.a'-β_!,g	∨PQ,bYXdRRRl~∀~∃m-π%∨M&1∨!t@@@@↓%)+I≤Q,g
%∨'&!,bY,HRRv~(~∃7%5β∂≤1=!:@@@@A%∃)+%≤!%≠β∂8Q,bR$v~∀~)7β1∪L1∨!:@@@@A%)U%≤Qβa∪&Q,DRRv~(~∃7'Y≠+_1=!:@@@@A%∃)+%≤!'-≠+0Q'-β0u-β→m,c:YXdRRv4∀~∃7Y'	∪,a∨!:@@@@AI)+%8Q'-≠U_Pb\@←'-β0u-β→m,e:YXbRRv4∀~∃7Y≠β↔
a∨!:@@@@AI)+%8Q≥.a,gπPQ'-β0u-β→m,c:YM-β_uYβ→7,I:Y'-¬_u-β17,g:$Rv~∀4∃7-β⊃λ1∨!t@@@@@A%Q+%≤QXgβ	λ!,bY,HRRv~(~∃7-M+∧1∨A:@@@@@A%∃)+%≤!,g'+λQ,bYXdRRv4∀~∃7I-≠+_a∨!:@@@@AI)+%8Q%-≠U_Q,b1,dRRl~∀~∃m+-πP1∨!:@@@@↓%)+I≤Q+-∃π(Q,DRRv~(~∃7!=&1∨!t@@@@@@A%∃)+%≤!!∨&QXbRRv4∀~∃7=%∪≥P1∨!:@@@AI)+%8Q∨%∪∃≥(Q,DRRv~(~∃7βa.1%∨Q≤1∨!t@@A%∃)+%≤!β1.1I∨)≤QXbY'-¬_u-β17,e:$Rv~∀4∃7%%5+_1∨A:@@@@A%Q+%≤QI%≠+_!,bY,HRRv~(~∃7)5β↔
1=!:@@@@A%∃)+%≤!≥.1Q%β≥&!π⊃↔%∃εQ,b1→∨εQI∨)≤R$Yπ⊃↔IεQ,HY→∨ε!,gπPRR@R$v~∀~)7π∨≥M)$1∨A:@@@A%)U%≤Qπ=≥')$!,bY,HY,fR$v~∀~)7)-β⊃λ1∨!t@@@@A%)U%≤Q≥∃.1)%¬≥&Q)Iβ≥&uI7,c:1,gβ	⊂Q)%β9&u!7Xc:Y,HRRRv4∀~∃7Q-'+∧a∨!:@@@@AI)+%8Q≥.a)%β≥LQ)%β9&u%7Xc:Y,M'+∧QQ%β≥&i!7,ctY,dR$Rv~∀4∃7)-5+_1∨A:@@@@A%Q+%≤QQ-≠+_!,bY,HRRv~(~∃7
Q∨1∨A:@@@@@A%∃)+%≤!))≠+0Q)∪≥Y%(Qπ!↔%εV1,LOC(TRANS))),CHKREC(V2,LOC(TRANS))) );

[TTMUL_OP]      RETURN(TTMUL(V1,V2));

[TINVRT_OP]     RETURN(TINVRT(V1));

[DEPR_OP]       BEGIN
	    IF V2 ≠ RNULL THEN RETURN(V2);
	    V2 ← DEPR(CELL:CAR[EXPRN:ARGS[E]]); ! in wldmod not arith;
	    CONSON(V2,EXPRN:ARGS[E]);
	    RETURN(EVALEXPR(V2,WLD));
	    END;

[FMAKE_OP]      RETURN(NEW_FRAME(
		    NEW_TRANS(CHKREC(V1,LOC(ROTN)),CHKREC(V2,LOC(V3ECT)) ) ));

[TFMAKE_OP]     RETURN(NEW_FRAME(V1));

[SSBRTN_OP]     CASE (ETYP←SVAL:VAL[V1]) OF
		  BEGIN

    [SQRT_OP]       RETURN(NEW_SVAL(SQRT(SVAL:VAL[V2])));
    [SIN_OP]        RETURN(NEW_SVAL(SIND(SVAL:VAL[V2])));
    [COS_OP]        RETURN(NEW_SVAL(COSD(SVAL:VAL[V2])));
    [TAN_OP]        RETURN(NEW_SVAL(SIND(SVAL:VAL[V2])/COSD(SVAL:VAL[V2])));
    [ASIN_OP]       RETURN(NEW_SVAL(ASIN(SVAL:VAL[V2]) * DEG));
    [ACOS_OP]       RETURN(NEW_SVAL(ACOS(SVAL:VAL[V2]) * DEG));
    [ATAN2_OP]      RETURN(NEW_SVAL(ATAN2(SVAL:VAL[V2],SVAL:VAL[V3])*DEG));
    [LOG_OP]        RETURN(NEW_SVAL(LOG(SVAL:VAL[V2])));
    [EXP_OP]        RETURN(NEW_SVAL(EXP(SVAL:VAL[V2])));
    [TIME_OP]       RETURN(NEW_SVAL(SVAL:VAL[V2]+1.0))

		  END;

[AREF_OP]       RETURN(GETVALUE(ARRAYREF(E,WLD),WLD));

[CALL_OP]       CASE PROCDEF:DATATYPE[CELL:CAR[EXPRN:ARGS[E]]] OF
		  BEGIN
    [SVAL_DTYPE]    RETURN(FALSEV);
    [V3ECT_DTYPE]   RETURN(NILVECT);
    [ROTN_DTYPE]    RETURN(NILROTN);
    [TRANS_DTYPE]   RETURN(NILTRANS);
    [FRAME_DTYPE]   RETURN(NILDEPROACH);
    ELSE            RETURN(FALSEV)
		  END;

[LAST_OP]       END;

    USERERR(1,1,"EVALEXPR: INVALID OP");
    RETURN(NULL_RECORD);

    END;

END $$PRGID;